'''
2016年3月2日

微拓科技-张志波
'''
from init import PATH
import RPi.GPIO as GPIO
import time
import configparser
import sys
import qrcode

class Lcd12864:
    def __init__(self):
        #读取配置文件
        conf = configparser.ConfigParser()
        conf.read(PATH()+'init.conf')
        #初始化二维码Version
        self.size=3
        #延时
        self.delaytime=0.000001
        #初始化引脚信息
        self.RS=conf.getint('lcd12864','rs')#显示屏指令线
        self.RW=conf.getint('lcd12864','rw')
        self.EN=conf.getint('lcd12864','en')
        self.P=[conf.getint('lcd12864','p0'),
                conf.getint('lcd12864','p1'),
                conf.getint('lcd12864','p2'),
                conf.getint('lcd12864','p3'),
                conf.getint('lcd12864','p4'),
                conf.getint('lcd12864','p5'),
                conf.getint('lcd12864','p6'),
                conf.getint('lcd12864','p7')] #显示屏数据线

    #引脚模式设置
    #参数i为引脚编号,m为输入或输出模式
    def Pin(self,i,m):
        if m==0:
            GPIO.setup(i,GPIO.IN)
        elif m==1:
            GPIO.setup(i,GPIO.OUT)

    #电平设置
    #参数i为引脚编号,m为引脚电平高低
    def Level(self,i,m):
        if m==0:
            GPIO.output(i,GPIO.LOW)
        elif m==1:
            GPIO.output(i,GPIO.HIGH)

    #检测电平
    #参数i为引脚编号
    def ChkLevel(self,i):
        return GPIO.input(i)

    #转2进制
    #参数i为要转换的数字
    def ToT(self,i):
        arr = [0]*8
        for a in range(0,8):
            arr[a]=int(i%2)
            i=i/2
        return arr

    #写命令
    #参数i为要写入的命令
    def WriteCmd(self,i):
        #检测忙
        self.ChkBusy()
        self.Level(self.RS,0)
        self.Level(self.RW,0)
        self.Level(self.EN,1)
        time.sleep(self.delaytime)
        #写入
        self.BusWrite(i)
        self.Level(self.EN,0)
        time.sleep(self.delaytime)

    #写字符数据
    #参数i为要写入的数据
    def WriteData(self,i):
        #检测忙
        self.ChkBusy()
        self.Level(self.RS,1)
        self.Level(self.RW,0)
        self.Level(self.EN,1)
        time.sleep(self.delaytime)
        #写入
        self.BusWrite(i)
        self.Level(self.EN,0)
        time.sleep(self.delaytime)

    #数据总线写入
    #参数i为要写入总线的数据
    def BusWrite(self,i):
        #将要写入的数据转为2进制
        arr = self.ToT(i)
        m=0
        for n in self.P:
            self.Level(n,arr[m])
            m+=1

    #检查忙
    def ChkBusy(self):
        self.Level(self.RS,0)
        self.Level(self.RW,1)
        self.Level(self.EN,1)
        #写入检测忙指令
        self.BusWrite(0xff)
        self.Pin(self.EN,0)
        while (1):
            #检测输入电平
            if self.ChkLevel(self.EN)==1:
                break
            else:
                time.sleep(0.001)
        self.Pin(self.EN,1)
        self.Level(self.EN,0)

    #初始化引脚状态
    #参数0为字符模式,1为绘图模式
    def Init(self,i):
        GPIO.setmode(GPIO.BCM)
        self.Pin(self.RS,1)
        self.Pin(self.RW,1)
        self.Pin(self.EN,1)
        for m in self.P:
            self.Pin(m,1)
        #选择8位数据流
        #设置字符模式
        if i==0:
            #选择8位数总线,基本指令集
            self.WriteCmd(0x30)
            time.sleep(self.delaytime)
            #清屏
            self.WriteCmd(0x01)
            time.sleep(self.delaytime)
            #设置游标
            self.WriteCmd(0x0c)
            time.sleep(self.delaytime)
        #设置绘图模式
        elif i==1:
            #清屏
            self.Init(0)
            #选择8位数总线,扩展指令集
            self.WriteCmd(0x34)

    #发送字符串
    def SendWord(self,i,m=0x80):
        #检测字符串长度
        count=len(i)
        if count>0:
            #初始化
            self.Init(0)
            #初始地址
            self.WriteCmd(m)
            for a in range(0,count):
                #获取单个字符的ASCII码
                asi=ord(i[a:a+1])
                #写入字符
                self.WriteData(asi)
                
    #绘图文字信息
    def DrawWord(self,list,h,w):
        for b in range(1,17):
            h=h+1
            if h<32:
                self.WriteCmd(0x80+h)
                self.WriteCmd(0x80+w)      
            else:
                self.WriteCmd(0x80+h-32)
                self.WriteCmd(0x88+w)
            for a in range (1,3):
                wri=list[b*2-a]
                self.WriteData(wri)
    #绘图清屏
    def DrawClear(self):
        self.Init(1)
        #关闭绘图显示
        self.WriteCmd(0x34)
        for a in range(0,32):
            self.WriteCmd(0x80+a)
            self.WriteCmd(0x80)
            for b in range(0,32):
                self.WriteData(0x00)
        #开启绘图显示
        self.WriteCmd(0x36)
        
    #二维码信息转List
    def CodeToList(self,i):
        #建立数组,用于保存二维码信息
        list = [[['0']*16 for m in range(0,64)]]
        #计数器 记录截取到第几位
        count=int(0)
        #截取字符串 并保存到list中
        for b in range(0,64):
            for a in range(0,16):
                if count<len(i):
                    if a==self.size+4:
                        list[0][b+3][a+5]=i[count:count+2]+'000000'
                        count=count+2
                        break
                    else:
                        list[0][b+3][a+5]=i[count:count+8]
                        count=count+8
        return list

    #发送绘图信息    
    def SendDraw(self,i):
        self.DrawClear()
        list=self.CodeToList(i)
        for a in range(0,2):
            for b in range(0,32):
                self.WriteCmd(0x80+b)
                #记录写入数组中第几位
                bitcount=0
                #判断上下屏
                if a==0:
                    self.WriteCmd(0x80)
                else:
                    self.WriteCmd(0x80+8)
                for c in range(0,16):
                    if a==0:
                        str=int(list[0][b][c],2)
                    else:
                        str=int(list[0][b+32][c],2)
                    self.WriteData(str)
                    #WriteData(0xff)
                    time.sleep(self.delaytime)
class Conver:
    def __init__(self) :
        self.size=3
    #参数分别为要使用二维码显示的文字和二维码Version
    def bin(self,text):
        #初始化二进制字符串
        qrc_2=''
        qr = qrcode.QRCode(
            # 范围为1到40，表示二维码的大小,如果想让程序自动生成，将值设置为 None 并使用 fit=True 参数即可。
            version=self.size,
            # 二维码的纠错范围，可以选择4个常量
            error_correction=qrcode.constants.ERROR_CORRECT_L,
            # 每个点的像素个数
            box_size=1,
        )
        qr.add_data(text)
        # 以字符形式输出
        qr_number = qr.print_number()
        #x轴
        for x in range(0, (self.size * 4 + 18)):
            for two in range(0,2):
            #y轴
                for y in range(0, (self.size * 4 + 17)):
                    if (x % 2 == 0):
                        if(qr_number[y][x] == 0 or qr_number[y][x] == 2):
                            qrc_2=qrc_2+'00'
                        else:
                            qrc_2=qrc_2+'11'
                    else:
                        if(qr_number[y][x] == 0 or qr_number[y][x] == 1):
                            qrc_2=qrc_2+'00'
                        else:
                            qrc_2=qrc_2+'11'
        return qrc_2
class Display:
    def __init__(self):
        self.lcd12864=Lcd12864()
    def startDraw(self,monitore_data):
        self.lcd12864.SendDraw(Conver().bin(monitore_data))
        self.lcd12864.DrawWord(list=[0x00,0x08,0x00,0x04,0x00,0x22,0x7F,0x11,
      0xC9,0x09,0x49,0x87,0x49,0x41,0x49,0x21,
      0x49,0x19,0x49,0x07,0x49,0x41,0x7F,0x81,
      0x00,0x41,0x80,0x3F,0x00,0x01,0x00,0x00],h=8,w=7)
        self.lcd12864.DrawWord(list=[0x80,0x00,0x82,0x80,0x82,0x40,0x82,0x30,
      0xFE,0x0F,0x82,0x00,0x82,0x00,0x82,0x00,
      0x82,0x00,0x82,0x00,0xFE,0xFF,0x82,0x00,
      0x82,0x00,0x82,0x00,0x80,0x00,0x00,0x00],h=24,w=7)
        self.lcd12864.DrawWord(list=[0x00,0x00,0xFC,0x7F,0x01,0x00,0x02,0x00,
      0x06,0x00,0x00,0x00,0x02,0x00,0x02,0x00,
      0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x40,
      0x02,0x80,0xFE,0x7F,0x00,0x00,0x00,0x00],h=8,w=15)
        self.lcd12864.DrawWord(list=[0x10,0x01,0x88,0x00,0xC4,0xFF,0xA3,0x40,
      0xBC,0x3E,0xA0,0x02,0xBF,0x02,0xA0,0x3E,
      0xBC,0x90,0x20,0x48,0xD8,0x33,0x17,0x0C,
      0x90,0x33,0x78,0xC0,0x10,0x40,0x00,0x00],h=0,w=1)
        self.lcd12864.DrawWord(list=[0x80,0x00,0x40,0x00,0x20,0x00,0xF8,0xFF,
      0x07,0x00,0x24,0x01,0x24,0xFD,0x24,0x45,
      0x25,0x45,0x26,0x45,0x24,0x45,0x24,0x45,
      0x24,0xFD,0x24,0x01,0x04,0x00,0x00,0x00],h=16,w=1)
        self.lcd12864.DrawWord(list=[0x10,0x02,0x10,0x42,0x10,0x81,0xFF,0x7F,
      0x90,0x00,0x50,0x00,0x04,0x20,0x84,0x20,
      0x84,0x20,0x84,0x20,0x84,0x20,0x84,0x20,
      0x84,0x20,0xFE,0x7F,0x04,0x00,0x00,0x00],h=0,w=9)
        self.lcd12864.DrawWord(list=[0x10,0x22,0x10,0x42,0xFF,0x7F,0x10,0x01,
      0x94,0x00,0xC4,0x7F,0x44,0x44,0x5F,0x44,
      0x44,0x44,0xC4,0x7F,0x44,0x44,0x5F,0x44,
      0x44,0x44,0xC4,0x7F,0x04,0x00,0x00,0x00],h=16,w=9)
        self.lcd12864.DrawWord(list=[0x00,0x40,0x10,0x40,0x10,0x40,0x90,0x40,
      0x10,0x43,0x10,0x5C,0x11,0x40,0x16,0x40,
      0x10,0x50,0x10,0x4C,0x10,0x43,0xD0,0x40,
      0x18,0x40,0x10,0x60,0x00,0x40,0x00,0x00],h=0,w=0)
        self.lcd12864.DrawWord(list=[0x08,0x40,0x88,0x48,0x88,0x48,0xC8,0x28,
      0xA9,0x24,0x9E,0x12,0x88,0x19,0x88,0x24,
      0x68,0x62,0x08,0x00,0xE0,0x0F,0x00,0x40,
      0x00,0x80,0xFF,0x7F,0x00,0x00,0x00,0x00],h=16,w=0)
        self.lcd12864.DrawWord(list=[0x80,0x00,0x82,0x80,0x82,0x40,0x82,0x30,
      0xFE,0x0F,0x82,0x00,0x82,0x00,0x82,0x00,
      0x82,0x00,0x82,0x00,0xFE,0xFF,0x82,0x00,
      0x82,0x00,0x82,0x00,0x80,0x00,0x00,0x00],h=0,w=8)
        self.lcd12864.DrawWord(list=[0x00,0x00,0xFC,0x7F,0x01,0x00,0x02,0x00,
      0x06,0x00,0x00,0x00,0x02,0x00,0x02,0x00,
      0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x40,
      0x02,0x80,0xFE,0x7F,0x00,0x00,0x00,0x00],h=16,w=8)
    def startWord(self,monitore_data):
        self.lcd12864.SendWord(monitore_data)
    def startClear(self):
        self.lcd12864.DrawClear()